package init.luoyu.easymonitor.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import init.luoyu.easymonitor.base.constant.CommonConstant;
import init.luoyu.easymonitor.base.model.ResponseData;
import init.luoyu.easymonitor.base.model.ResponsePage;
import init.luoyu.easymonitor.base.model.SelectDto;
import init.luoyu.easymonitor.base.model.ServiceResult;
import init.luoyu.easymonitor.base.model.input.PageInput;
import init.luoyu.easymonitor.base.utils.CollectorsUtil;
import init.luoyu.easymonitor.base.utils.CommonUtil;
import init.luoyu.easymonitor.base.utils.SpringContextUtil;
import init.luoyu.easymonitor.server.device.business.enums.DeviceLinkType;
import init.luoyu.easymonitor.server.device.business.model.base.UpdateCoreDeviceGroup;
import init.luoyu.easymonitor.server.device.business.model.dto.DeviceTreeDto;
import init.luoyu.easymonitor.server.device.business.model.input.CreateOrUpdateDeviceInput;
import init.luoyu.easymonitor.server.device.business.service.IDeviceGroupService;
import init.luoyu.easymonitor.server.device.business.service.IDeviceService;
import init.luoyu.easymonitor.server.device.repository.model.CoreDevice;
import init.luoyu.easymonitor.server.device.repository.model.CoreDeviceGroup;
import init.luoyu.easymonitor.server.device.repository.model.DeviceLink;
import init.luoyu.easymonitor.server.device.repository.service.IDeviceLinkService;
import init.luoyu.easymonitor.server.item.repository.model.DeviceMonitorItem;
import init.luoyu.easymonitor.server.item.repository.service.IDeviceMonitorItemService;
import io.swagger.annotations.*;
import lombok.Data;
import org.elasticsearch.common.recycler.Recycler;
import org.modelmapper.ModelMapper;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @author LuoYu
 * date 2021/4/28
 */
@RestController
@CrossOrigin
@RequestMapping(value = "/api/device")
@Api(tags = "设备模块")
public class DeviceController {


    @Resource
    private IDeviceGroupService deviceGroupService;

    @Resource
    private IDeviceService deviceService;

    @Resource
    private IDeviceLinkService deviceLinkService;



    @PostMapping(value = "/createorupdategroup")
    @ApiOperation(value = "创建/更新主机组")
    public ServiceResult<Long> createOrUpdateGroup(@RequestBody @Valid CreateOrUpdateGroup group){
        UpdateCoreDeviceGroup updateCoreDeviceGroup = new ModelMapper().map(group, UpdateCoreDeviceGroup.class);
        return deviceGroupService.createOrUpdate(updateCoreDeviceGroup);
    }



    @PostMapping(value = "/createorupdatedevice")
    @ApiOperation(value = "创建/更新主机")
    public ServiceResult<Long> createOrUpdateDevice(@RequestBody @Valid CreateOrUpdateDeviceInput input){
        return deviceService.createOrUpdate(input,0L);
    }


    @PostMapping(value = "/grouppage")
    @ApiOperation(value = "获取主机群组分页")
    public ResponsePage<CoreDeviceGroup> groupPage(@RequestBody @Valid PageInput input) {
        Page<CoreDeviceGroup> page = new Page<>(input.getPageIndex(),input.getPageSize());
        IPage<CoreDeviceGroup> groupIPage = deviceGroupService.getMapper().page(page);
        List<CoreDeviceGroup> records = groupIPage.getRecords();
        ResponsePage<CoreDeviceGroup> responsePage = new ResponsePage<>();
        responsePage.setTotal(CommonUtil.isEmptyCollection(records) ? 0L : groupIPage.getTotal());
        responsePage.setData(records);
        return responsePage;
    }


    @DeleteMapping(value = "/deleteGroup")
    @ApiOperation(value = "删除主机群组")
    @ApiImplicitParam(name = "id",value = "群组id",required = true)
    public ResponseData<Boolean> deleteGroup(@RequestParam(value = "id") Long id) {
        return new ResponseData<>(deviceGroupService.delete(id));
    }


    @GetMapping(value = "/getTree")
    @ApiOperation(value = "获取设备树形结构数据")
    public ResponseData<List<DeviceTreeDto>> getDeviceTree() {
        QueryWrapper<DeviceLink> linkQuery = new QueryWrapper<>();
        linkQuery.select("type","target","deviceId").eq("type", DeviceLinkType.LINK_GROUP.getType());
        List<DeviceLink> links = deviceLinkService.list(linkQuery);
        if(CommonUtil.isEmptyCollection(links)) {
            return ResponseData.success(null);
        }
        Set<Long> groupIdSet = links.stream().map(DeviceLink::getTarget).collect(Collectors.toSet());
        //查询主机群组
        QueryWrapper<CoreDeviceGroup> groupQuery = new QueryWrapper<>();
        groupQuery.select("id","name").eq("isDeleted",false).in("id",groupIdSet);
        List<CoreDeviceGroup> groups = deviceGroupService.getMapper().selectList(groupQuery);
        if(CommonUtil.isEmptyCollection(groups)) {
            return ResponseData.success(null);
        }
        //查询设备
        QueryWrapper<CoreDevice> deviceQuery = new QueryWrapper<>();
        Set<Long> deviceIdSet = links.stream().map(DeviceLink::getDeviceId).collect(Collectors.toSet());
        deviceQuery.select("id","name").eq("isDeleted",false).in("id",deviceIdSet);
        List<CoreDevice> devices = deviceService.getMapper().selectList(deviceQuery);
        if(CommonUtil.isEmptyCollection(devices)) {
            return ResponseData.success(null);
        }
        //组装数据
        Map<Long, String> deviceMap = devices.stream().collect(Collectors.toMap(CoreDevice::getId, CoreDevice::getName));
        Map<Long, String> groupMap = groups.stream().collect(Collectors.toMap(CoreDeviceGroup::getId, CoreDeviceGroup::getName));
        Map<Long, List<DeviceLink>> listMap = links.stream().collect(Collectors.groupingBy(DeviceLink::getTarget));
        List<DeviceTreeDto> tree = Lists.newArrayList();
        listMap.forEach((k,v)-> {
            String title = groupMap.get(k);
            if(!CommonUtil.isEmptyStr(title) && !CommonUtil.isEmptyCollection(v)) {
                DeviceTreeDto dto = new DeviceTreeDto();
                dto.setKey(k);
                dto.setTitle(title);
                dto.setIsLeaf(false);
                List<DeviceTreeDto> childList = Lists.newArrayList();
                for (DeviceLink link : v) {
                    String childTitle = deviceMap.get(link.getDeviceId());
                    if(!CommonUtil.isEmptyStr(childTitle)) {
                        DeviceTreeDto child = new DeviceTreeDto();
                        child.setIsLeaf(true);
                        child.setKey(link.getDeviceId());
                        child.setTitle(childTitle);
                        childList.add(child);
                    }
                }
                dto.setChildren(childList);
                if(!CommonUtil.isEmptyCollection(childList)) {
                    tree.add(dto);
                }
            }
        });
        return ResponseData.success(tree);
    }








    @GetMapping(value = "/groupselect")
    @ApiOperation(value = "获取主机群组下拉框数据")
    public ResponseData<List<SelectDto>> getGroupSelect() {
        QueryWrapper<CoreDeviceGroup> groupQueryWrapper = new QueryWrapper<>();
        groupQueryWrapper.select("id","name").eq("status", CommonConstant.STATUS_ENABLE);
        List<CoreDeviceGroup> groups = deviceGroupService.getMapper().selectList(groupQueryWrapper);
        List<SelectDto> selectList = CollectorsUtil.switcher(groups, item -> {
            SelectDto dto = new SelectDto();
            dto.setId(item.getId());
            dto.setKey(String.valueOf(item.getId()));
            dto.setLabel(item.getName());
            return dto;
        });
        return ResponseData.success(selectList);
    }


    @DeleteMapping(value = "/delete")
    @ApiOperation(value = "删除设备")
    @ApiImplicitParam(name = "id",value = "设备id",required = true)
    public ResponseData<Boolean> delete(@RequestParam(value = "id") Long id) {
            return new ResponseData<>(deviceService.delete(id));
    }








    @PostMapping(value = "/page")
    @ApiOperation(value = "分页获取设备信息")
    public ResponsePage<DeviceInfo> getDeviceInfoPage(@RequestBody @Valid PageInput pageInput) {
        Page<CoreDevice> page = new Page<>(pageInput.getPageIndex(),pageInput.getPageSize());
        IPage<CoreDevice> coreDeviceIPage = deviceService.getMapper().page(page);
        List<CoreDevice> records = coreDeviceIPage.getRecords();
        List<DeviceInfo> deviceInfos = Lists.newArrayList();
        ResponsePage<DeviceInfo> responsePage = new ResponsePage<>();
        if(CommonUtil.isEmptyCollection(records)) {
            responsePage.setTotal(0L);
            responsePage.setData(null);
            return responsePage;
        }
        QueryWrapper<DeviceMonitorItem> itemQuery  = new QueryWrapper<>();
        itemQuery.select("id","deviceId").in("deviceId",records.stream().map(CoreDevice::getId).collect(Collectors.toList()));
        IDeviceMonitorItemService itemService = SpringContextUtil.getBean(IDeviceMonitorItemService.class);
        List<DeviceMonitorItem> items = itemService.list(itemQuery);
        Map<Long, List<DeviceMonitorItem>> map = CommonUtil.isEmptyCollection(items)
                ? Maps.newHashMap() : items.stream().collect(Collectors.groupingBy(DeviceMonitorItem::getDeviceId));

        ModelMapper modelMapper = new ModelMapper();
        for (CoreDevice record : records) {
            DeviceInfo deviceInfo = modelMapper.map(record, DeviceInfo.class);
            deviceInfo.setId(String.valueOf(record.getId()));
            List<DeviceMonitorItem> monitorItems = map.get(record.getId());
            deviceInfo.setItemNum(CommonUtil.isEmptyCollection(monitorItems) ? 0 : monitorItems.size());
            deviceInfos.add(deviceInfo);
        }
        responsePage.setData(deviceInfos);
        responsePage.setTotal(coreDeviceIPage.getTotal());
        return responsePage;
    }





























}
@Data
@ApiModel(description = "创建或更新主机组实体")
class CreateOrUpdateGroup {

    @ApiModelProperty(value = "群组id  不传为新增")
    private Long id;

    @ApiModelProperty(value = "群组名称",required = true)
    @NotBlank(message = "主机群组名称不能为空")
    private String name;


    @ApiModelProperty(value = "描述")
    private String bio;
}

@Data
@ApiModel(description = "设备信息")
class  DeviceInfo {

    @ApiModelProperty(value = "id")
    private String id;

    @ApiModelProperty(value = "设备名称")
    private String name;

    @ApiModelProperty(value = "设备描述")
    private String bio;

    @ApiModelProperty(value = "ip地址")
    private String ipAddress;

    @ApiModelProperty(value = "创建时间")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "监控项数量")
    private Integer itemNum;

    @ApiModelProperty(value = "连接状态")
    private boolean connection;

}







